/*链表实现*/
enum List{
    // Cons: 包含一个元素和一个指向下一个节点的指针的元组结构
    Cons(String, Box<List>),
    // Nil: 表示一个链表节点的末端
    Nil,
}

impl List {
    // 新建一个链表
    fn new() -> List {
        List::Nil
    }
    // 在前面加一个元素节点，并且链接旧的链表和返回新的链表
    fn prepend(self, elem: String) -> List {
        List::Cons(elem, Box::new(self))
    }

    // 返回链表的长度
    fn len(&self) -> u32 {
        match *self {
            // 因为`self`是借用的，所以不能转移 tail 的所有权
            // 因此使用 tail 的引用
            List::Cons(_, ref tail) => 1 + tail.len(), //递归
            List::Nil => 0
        }
    }
    //返回链表长度
    fn len2(&self) -> u32 {
        let mut r = self;
        let mut len = 0;
        //使用循环
        loop {
            match *r {
                List::Cons(_, ref tail) => {
                    len += 1;
                    r = tail;
                }
                List::Nil => break,
            }
        }
        return len;
    }
    // 返回连链表的字符串表达形式
    fn stringify(&self) -> String {
        match *self {
            List::Cons(ref head, ref tail) => {
                format!("{},{}", head, tail.stringify())
            },
            List::Nil => {
                format!("Nil")
            }
        }
    }
    // 返回连链表的字符串表达形式
    fn stringify2(&self) -> String {
        let mut r = self;
        let mut s = String::new();
        loop {
            match *r {
                List::Cons(ref head, ref tail) => {
                    // let sub = format!("{},", head);
                    // s.push_str(&sub);
                    s = format!("{},{}", s, head);
                    r = tail;
                },
                List::Nil => {
                    break;
                }
            }
        }
        return s;

    }

}

pub fn list_demo(){
    let mut list = List::new();

    list = list.prepend(String::from("hello"));
    list = list.prepend(String::from("world"));
    list = list.prepend(String::from("ok"));

    println!("linked list has length: {}", list.len());
    println!("linked list has length: {}", list.len2());
    println!("{}", list.stringify());
    println!("{}", list.stringify2());
}
